import React from 'react';
import { Menu, Dropdown, Icon, Empty, Select } from 'antd';
import styles from './index.less';

const { Option } = Select;

const filterTree = (tree, str = '', labelStr = '') =>
    tree.map(({ children, value, label, ...props }) => {
        const key = `${str}${str ? '-' : ''}${value}`;
        const fullLabel = `${labelStr}${labelStr ? '/' : ''}${label}`;
        return {
            children: children && children.length > 0 ? filterTree(children, key, fullLabel) : '',
            value,
            key,
            label,
            fullLabel,
            ...props
        };
    });

const getFilteredData = (tree, arr = []) =>
    tree.forEach(({ children, ...rest }) => {
        arr.push({ children, ...rest });
        if (children && children.length > 0) {
            getFilteredData(children, arr);
        }
    });

const DropDownCascader = React.forwardRef(
    (
        {
            value,
            options,
            maxCount = 3,
            onChange,
            changeOnLastLevel = false,
            disabled = false,
            dropDownProps,
            ...restProps
        },
        ref
    ) => {
        // console.log(value);
        const [visible, setVisible] = React.useState(false);
        const [openIndex, setOpenIndex] = React.useState([]);
        const [selectedKeys, setSelectedKeys] = React.useState([]);
        const [searchInput, setSearchInput] = React.useState('');
        const firstRef = React.useRef(true);
        // console.log('selectedKeys', selectedKeys);

        const finalData = React.useMemo(() => filterTree(options), [options]);

        const finalDataList = React.useMemo(() => {
            const tempList = [];
            getFilteredData(finalData, tempList);
            return tempList;
        }, [finalData]);

        const handleItemClick = val => {
            const { item, key } = val;
            // console.log('item', item);
            const {
                props: { start, open, temp }
            } = item;
            if (changeOnLastLevel && temp?.children?.length > 0) {
                return;
            }
            const arr = openIndex.slice(0, start).concat([open]);
            setOpenIndex(arr);
            let tempArr = [];
            if (selectedKeys.includes(key)) {
                tempArr = selectedKeys.filter(_ => _ !== key && !key.startsWith(_));
            } else {
                tempArr = [...selectedKeys.filter(_ => !key.startsWith(_) && !_.startsWith(key)), val.key];
            }
            setSelectedKeys(tempArr);
        };

        const handleItemHover = val => {
            const { start, open } = val;
            const arr = openIndex.slice(0, start).concat([open]);
            setOpenIndex(arr);
        };

        const handleSelectSearch = str => {
            setSearchInput(str.trim());
        };

        React.useEffect(() => {
            if (firstRef.current) {
                firstRef.current = false;
                return;
            }
            if (selectedKeys && selectedKeys.length > 0) {
                const arrTemp = selectedKeys.map(a => {
                    const temp = a.split('-');
                    return temp[temp.length - 1];
                });
                if (maxCount === 1 && selectedKeys.length > maxCount) {
                    onChange([arrTemp.pop()]);
                } else {
                    onChange(arrTemp);
                }
                if (maxCount === 1 && selectedKeys.length >= maxCount) {
                    setVisible(false);
                }
            } else {
                onChange(undefined);
            }
        }, [JSON.stringify(selectedKeys)]);

        React.useEffect(() => {
            const temp = value || [];
            if (JSON.stringify(temp) === JSON.stringify(selectedKeys)) {
                return;
            }
            if (finalDataList && finalDataList.length > 0 && value && value.length > 0) {
                const arr = [];
                value.forEach(item => {
                    const val = finalDataList.find(item2 => `${item2.value}` === `${item}`)?.key;
                    if (val) {
                        arr.push(val);
                    }
                });
                setSelectedKeys(arr);
            } else {
                setSelectedKeys([]);
            }
        }, [JSON.stringify(value), finalDataList]);

        const renderOverlay = tree => {
            if (tree && tree.length > 0) {
                return (
                    <div
                        style={{
                            display: 'flex',
                            background: '#fff',
                            boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
                            borderRadius: 4,
                            overflow: 'hidden',
                            maxHeight: 200
                        }}
                    >
                        <Menu
                            key="0"
                            onClick={handleItemClick}
                            multiple
                            selectedKeys={selectedKeys.map(i => i.split('-')[0])}
                        >
                            {tree.map((item, index) => (
                                <Menu.Item
                                    key={item.key}
                                    open={index}
                                    start={0}
                                    temp={item}
                                    onMouseEnter={() => handleItemHover({ start: 0, open: index })}
                                    disabled={
                                        maxCount > 1 &&
                                        selectedKeys.length >= maxCount &&
                                        !selectedKeys.map(i => i.split('-')[0]).includes(item.key)
                                    }
                                >
                                    <div style={{ overflow: 'hidden', whitespace: 'nowrap', textOverflow: 'ellipsis' }}>
                                        {item.label}
                                    </div>
                                    {item.children?.length > 0 && <Icon type="right" className={styles.customIcon} />}
                                </Menu.Item>
                            ))}
                        </Menu>
                        {openIndex.map((item, index) => {
                            let tempData = [...tree];
                            new Array(index + 1).fill(0).forEach((t, i) => {
                                tempData = tempData[openIndex[i]].children;
                            });
                            if (tempData && tempData.length > 0) {
                                return (
                                    <Menu
                                        key={`${index + 1}`}
                                        onClick={handleItemClick}
                                        multiple
                                        selectedKeys={selectedKeys.map(i =>
                                            i
                                                .split('-')
                                                .filter((_, i2) => i2 < index + 2)
                                                .join('-')
                                        )}
                                    >
                                        {tempData.map((item2, index2) => (
                                            <Menu.Item
                                                key={item2.key}
                                                open={index2}
                                                start={index + 1}
                                                temp={item2}
                                                onMouseEnter={() => handleItemHover({ start: index + 1, open: index2 })}
                                                disabled={
                                                    maxCount > 1 &&
                                                    selectedKeys.length >= maxCount &&
                                                    !selectedKeys
                                                        .map(i =>
                                                            i
                                                                .split('-')
                                                                .filter((_, i2) => i2 < index + 2)
                                                                .join('-')
                                                        )
                                                        .includes(item2.key)
                                                }
                                            >
                                                <div
                                                    style={{
                                                        overflow: 'hidden',
                                                        whitespace: 'nowrap',
                                                        textOverflow: 'ellipsis'
                                                    }}
                                                >
                                                    {item2.label}
                                                </div>
                                                {item2.children?.length > 0 && (
                                                    <Icon type="right" className={styles.customIcon} />
                                                )}
                                            </Menu.Item>
                                        ))}
                                    </Menu>
                                );
                            }
                            return null;
                        })}
                    </div>
                );
            }
            return (
                <div
                    style={{
                        display: 'flex',
                        justifyContent: 'center',
                        background: '#fff',
                        boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
                        borderRadius: 4,
                        overflow: 'hidden',
                        maxHeight: 200
                    }}
                >
                    <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
                </div>
            );
        };

        return (
            <div className={styles.dropdownWrap}>
                <Dropdown
                    overlay={renderOverlay(finalData)}
                    ref={ref}
                    overlayClassName={styles.customDropDown}
                    trigger={['click']}
                    getPopupContainer={trigger => trigger.parentElement}
                    visible={visible && !searchInput}
                    onVisibleChange={v => setVisible(v)}
                    disabled={disabled}
                    {...dropDownProps}
                >
                    <Select
                        showArrow
                        mode="multiple"
                        allowClear
                        value={selectedKeys}
                        style={{ width: '100%' }}
                        placeholder="请选择"
                        optionLabelProp="label"
                        optionFilterProp="full"
                        open={!!searchInput}
                        // onFocus={() => setVisible(true)}
                        onDropdownVisibleChange={() => setVisible(true)}
                        onChange={val => setSelectedKeys(val)}
                        onSearch={handleSelectSearch}
                        onSelect={() => handleSelectSearch('')}
                        {...restProps}
                    >
                        {finalDataList?.map(item => (
                            <Option
                                key={item.key}
                                value={item.key}
                                label={item.label}
                                full={item.fullLabel}
                                disabled={
                                    (maxCount > 1 &&
                                        selectedKeys.length >= maxCount &&
                                        !selectedKeys.includes(item.key)) ||
                                    (changeOnLastLevel && item?.children?.length > 0)
                                }
                                title={item.fullLabel}
                            >
                                {item.fullLabel}
                            </Option>
                        ))}
                    </Select>
                </Dropdown>
            </div>
        );
    }
);

export default DropDownCascader;
